// ==UserScript==
// @name         Verizon BYOD Device Checker
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  检查Verizon BYOD页面上的设备是否在黑名单中
// @author       You
// @match        https://www.verizon.com/business/shop/products/devices/smartphones/byod*
// @grant        none
// @require      https://unpkg.com/xlsx/dist/xlsx.full.min.js
// ==/UserScript==

(function() {
    'use strict';

    // 存储检查结果的数组，用于导出
    let checkResults = [];
    // 新增：存储IMEI到结果的Map，便于顺序导出
    let imeiResultMap = {};
    // 新增：存储当前批次的IMEI顺序
    let currentImeiOrder = [];
    // 新增：存储IMEI到"正在检查"div的Map
    let imeiDivMap = {};

    // 创建状态显示元素
    function createStatusElement() {
        const statusDiv = document.createElement('div');
        statusDiv.id = 'device-status-checker';
        statusDiv.style.position = 'fixed';
        statusDiv.style.top = '10px';
        statusDiv.style.right = '10px';
        statusDiv.style.padding = '15px';
        statusDiv.style.backgroundColor = '#f8f8f8';
        statusDiv.style.border = '1px solid #ddd';
        statusDiv.style.borderRadius = '5px';
        statusDiv.style.zIndex = '9999';
        statusDiv.style.boxShadow = '0 0 10px rgba(0,0,0,0.1)';
        statusDiv.style.fontSize = '16px';
        statusDiv.style.fontFamily = 'Arial, sans-serif';
        statusDiv.style.minWidth = '350px';
        
        // 创建标题
        const title = document.createElement('h3');
        title.style.margin = '0 0 15px 0';
        title.style.fontSize = '18px';
        title.textContent = '设备状态批量检查器';
        statusDiv.appendChild(title);
        
        // 创建IMEI输入框
        const inputContainer = document.createElement('div');
        inputContainer.style.marginBottom = '15px';
        inputContainer.style.display = 'flex';
        inputContainer.style.flexDirection = 'column';
        
        const imeiTextarea = document.createElement('textarea');
        imeiTextarea.id = 'imei-input';
        imeiTextarea.placeholder = '输入多个IMEI号码，每行一个';
        imeiTextarea.style.width = '100%';
        imeiTextarea.style.height = '100px';
        imeiTextarea.style.padding = '8px';
        imeiTextarea.style.marginBottom = '10px';
        imeiTextarea.style.fontSize = '16px';
        imeiTextarea.style.borderRadius = '4px';
        imeiTextarea.style.border = '1px solid #ccc';
        imeiTextarea.style.resize = 'vertical';
        inputContainer.appendChild(imeiTextarea);
        
        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.justifyContent = 'space-between';
        
        const checkButton = document.createElement('button');
        checkButton.textContent = '批量检查';
        checkButton.style.padding = '8px 15px';
        checkButton.style.cursor = 'pointer';
        checkButton.style.fontSize = '16px';
        checkButton.style.backgroundColor = '#4CAF50';
        checkButton.style.color = 'white';
        checkButton.style.border = 'none';
        checkButton.style.borderRadius = '4px';
        checkButton.style.fontWeight = 'bold';
        checkButton.style.flex = '1';
        checkButton.style.marginRight = '10px';
        checkButton.onclick = function() {
            const imeiText = document.getElementById('imei-input').value;
            if (imeiText.trim()) {
                // 分割多行IMEI并去除空白
                const imeis = imeiText.split('\n')
                    .map(imei => imei.trim())
                    .filter(imei => imei.length > 0);
                
                if (imeis.length > 0) {
                    // 清空结果区域和结果数组
                    checkResults = [];
                    updateStatus('开始批量检查...', true);
                    
                    // 创建结果容器
                    const resultsContainer = document.createElement('div');
                    resultsContainer.id = 'results-container';
                    resultsContainer.innerHTML = '';
                    
                    // 替换状态消息区域
                    const statusMessage = document.getElementById('status-message');
                    if (statusMessage) {
                        statusMessage.innerHTML = '';
                        statusMessage.appendChild(resultsContainer);
                    }
                    
                    // 隐藏导出按钮
                    const exportButton = document.getElementById('export-button');
                    if (exportButton) {
                        exportButton.style.display = 'none';
                    }
                    
                    // 批量检查
                    batchCheckDevices(imeis);
                } else {
                    updateStatus('请输入有效的IMEI号码', false);
                }
            } else {
                updateStatus('请输入有效的IMEI号码', false);
            }
        };
        buttonContainer.appendChild(checkButton);
        
        const clearButton = document.createElement('button');
        clearButton.textContent = '清空';
        clearButton.style.padding = '8px 15px';
        clearButton.style.cursor = 'pointer';
        clearButton.style.fontSize = '16px';
        clearButton.style.backgroundColor = '#f44336';
        clearButton.style.color = 'white';
        clearButton.style.border = 'none';
        clearButton.style.borderRadius = '4px';
        clearButton.style.fontWeight = 'bold';
        clearButton.style.flex = '1';
        clearButton.onclick = function() {
            document.getElementById('imei-input').value = '';
            updateStatus('等待输入IMEI...', true);
            // 隐藏导出按钮
            const exportButton = document.getElementById('export-button');
            if (exportButton) {
                exportButton.style.display = 'none';
            }
            // 清空结果数组
            checkResults = [];
        };
        buttonContainer.appendChild(clearButton);
        
        inputContainer.appendChild(buttonContainer);
        statusDiv.appendChild(inputContainer);
        
        // 创建状态显示区域
        const statusMessage = document.createElement('div');
        statusMessage.id = 'status-message';
        statusMessage.textContent = '等待输入IMEI...';
        statusMessage.style.padding = '10px';
        statusMessage.style.backgroundColor = '#f5f5f5';
        statusMessage.style.borderRadius = '4px';
        statusMessage.style.minHeight = '150px';
        statusMessage.style.maxHeight = '300px';
        statusMessage.style.overflowY = 'auto';
        statusMessage.style.wordBreak = 'break-word';
        statusDiv.appendChild(statusMessage);
        
        // 创建导出按钮（初始隐藏）
        const exportButton = document.createElement('button');
        exportButton.id = 'export-button';
        exportButton.textContent = '导出Excel';
        exportButton.style.padding = '8px 15px';
        exportButton.style.cursor = 'pointer';
        exportButton.style.fontSize = '16px';
        exportButton.style.backgroundColor = '#2196F3';
        exportButton.style.color = 'white';
        exportButton.style.border = 'none';
        exportButton.style.borderRadius = '4px';
        exportButton.style.fontWeight = 'bold';
        exportButton.style.marginTop = '15px';
        exportButton.style.width = '100%';
        exportButton.style.display = 'none';
        exportButton.onclick = function() {
            exportToExcel();
        };
        statusDiv.appendChild(exportButton);
        
        document.body.appendChild(statusDiv);
        return statusDiv;
    }

    // 更新状态显示
    function updateStatus(message, isClean) {
        const statusMessage = document.getElementById('status-message');
        if (statusMessage) {
            // 将换行符转换为HTML换行
            statusMessage.innerHTML = message.replace(/\n/g, '<br>');
            statusMessage.style.color = isClean ? 'green' : 'red';
            statusMessage.style.fontWeight = 'bold';
        }
    }

    // 添加单个设备结果，返回div元素
    function addDeviceResult(imei, message, isClean, deviceModel = '未知') {
        const resultsContainer = document.getElementById('results-container');
        if (resultsContainer) {
            const resultItem = document.createElement('div');
            resultItem.style.padding = '8px';
            resultItem.style.margin = '5px 0';
            resultItem.style.borderRadius = '4px';
            resultItem.style.backgroundColor = isClean ? 'rgba(0, 128, 0, 0.1)' : 'rgba(255, 0, 0, 0.1)';
            resultItem.style.border = `1px solid ${isClean ? 'green' : 'red'}`;
            resultItem.style.color = isClean ? 'green' : 'red';
            resultItem.style.fontWeight = 'bold';
            // 新增：设置唯一id
            resultItem.id = 'result-' + imei;
            // 将换行符转换为HTML换行
            resultItem.innerHTML = message.replace(/\n/g, '<br>');
            resultsContainer.appendChild(resultItem);
            // 自动滚动到底部
            resultsContainer.scrollTop = resultsContainer.scrollHeight;
            return resultItem;
        }
        return null;
    }

    // 批量检查设备（并发版，最大并发数5）
    function batchCheckDevices(imeis) {
        const maxConcurrency = 5;
        let running = 0;
        let currentIndex = 0;
        let finishedCount = 0;
        checkResults = [];
        imeiResultMap = {};
        currentImeiOrder = imeis.slice(); // 保存顺序
        imeiDivMap = {};
        const total = imeis.length;

        function runNext() {
            // 如果全部完成，显示导出按钮
            if (finishedCount >= total) {
                const exportButton = document.getElementById('export-button');
                if (exportButton && checkResults.length > 0) {
                    exportButton.style.display = 'block';
                }
                return;
            }
            // 控制并发
            while (running < maxConcurrency && currentIndex < total) {
                const imei = imeis[currentIndex];
                currentIndex++;
                running++;
                // 新增：添加"正在检查"div并保存引用
                const checkingDiv = addDeviceResult(imei, `正在检查设备 ${imei}...`, true);
                imeiDivMap[imei] = checkingDiv;
                checkDeviceStatus(imei, function(message, isClean, deviceModel) {
                    const resultsContainer = document.getElementById('results-container');
                    // 新增：移除对应IMEI的"正在检查"div
                    if (resultsContainer && imeiDivMap[imei]) {
                        resultsContainer.removeChild(imeiDivMap[imei]);
                        delete imeiDivMap[imei];
                    }
                    // 添加检查结果
                    addDeviceResult(imei, message, isClean, deviceModel);
                    // 新增：结果存入Map
                    imeiResultMap[imei] = {
                        imei: imei,
                        黑白: isClean ? 'CLEAN (白名单)' : 'BLACKLISTED (黑名单)',
                        型号: deviceModel
                    };
                    checkResults.push({
                        序号: checkResults.length + 1,
                        imei: imei,
                        黑白: isClean ? 'CLEAN (白名单)' : 'BLACKLISTED (黑名单)',
                        型号: deviceModel
                    });
                    running--;
                    finishedCount++;
                    runNext(); // 继续补充请求
                });
            }
        }
        runNext();
    }

    // 检查设备状态
    function checkDeviceStatus(imei, callback) {
        const xhr = new XMLHttpRequest();
        // 使用正确的API URL
        xhr.open('POST', 'https://www.verizon.com/business/shop/devicesvc/mbt/prospect/device/validateDeviceId', true);
        
        // 添加所有必要的请求头
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
        xhr.setRequestHeader('Cache-Control', 'no-cache');
        xhr.setRequestHeader('Pragma', 'no-cache');
        xhr.setRequestHeader('Origin', 'https://www.verizon.com');
        xhr.setRequestHeader('Referer', 'https://www.verizon.com/business/shop/products/devices/smartphones/byod');
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.setRequestHeader('pageid', '/business/shop/products/devices/smartphones/byod');
        
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    try {
                        const response = JSON.parse(xhr.responseText);
                        console.log('validateDeviceId响应:', response);
                        
                        // 检查服务状态
                        if (response && response.serviceStatus) {
                            // 检查是否成功
                            if (response.serviceStatus.success === true) {
                                // 成功响应，设备在白名单中
                                const deviceInfo = response.deviceInfo || {};
                                const deviceName = deviceInfo.brandName && deviceInfo.name ? 
                                    `${deviceInfo.brandName} ${deviceInfo.name}` : '未知设备';
                                const statusMessage = `设备 ${imei} 状态: CLEAN (可用)\n设备型号: ${deviceName}`;
                                
                                if (callback) callback(statusMessage, true, deviceName);
                            } else {
                                // 失败响应，设备在黑名单中
                                const errorMsg = response.serviceStatus.statusMessage || '未知错误';
                                const statusMessage = `设备 ${imei} 状态: BLACKLISTED (黑名单)\n错误信息: ${errorMsg}`;
                                
                                if (callback) callback(statusMessage, false, '未知设备');
                            }
                        } else {
                            const statusMessage = `无法确定设备 ${imei} 的状态`;
                            if (callback) callback(statusMessage, false, '未知设备');
                        }
                    } catch (e) {
                        console.error('解析响应失败:', e);
                        const statusMessage = `设备 ${imei} 解析响应失败`;
                        if (callback) callback(statusMessage, false, '未知设备');
                    }
                } else {
                    const statusMessage = `设备 ${imei} API调用失败: ${xhr.status} - ${xhr.statusText}`;
                    console.error('API错误详情:', xhr.responseText);
                    if (callback) callback(statusMessage, false, '未知设备');
                }
            }
        };
        
        // 发送请求体
        const data = JSON.stringify({
            deviceId: imei
        });
        
        xhr.send(data);
    }

    // 导出Excel功能
    function exportToExcel() {
        if (!window.XLSX) {
            alert('Excel导出库未加载，请刷新页面重试');
            return;
        }
        if (!currentImeiOrder || currentImeiOrder.length === 0) {
            alert('没有可导出的数据');
            return;
        }
        try {
            // 新增：按输入顺序组装导出数据
            const formattedResults = currentImeiOrder.map((imei, idx) => {
                const result = imeiResultMap[imei] || {imei, 黑白: '无结果', 型号: '未知'};
                return {
                    序号: idx + 1,
                    imei: result.imei,
                    黑白: result.黑白,
                    型号: result.型号
                };
            });
            // 创建工作簿
            const wb = XLSX.utils.book_new();
            // 创建工作表
            const ws = XLSX.utils.json_to_sheet(formattedResults);
            // 设置IMEI列为文本格式，防止科学计数法
            const imeiCol = 1; // IMEI是第2列（从0开始）
            for (let i = 2; i <= formattedResults.length + 1; i++) { // 从第2行开始（第1行为表头）
                const cellRef = XLSX.utils.encode_cell({c: imeiCol, r: i - 1});
                if (ws[cellRef]) {
                    ws[cellRef].t = 's'; // 类型为字符串
                }
            }
            // 设置列宽
            ws['!cols'] = [
                {wch: 6},   // 序号
                {wch: 20},  // imei
                {wch: 25},  // 黑白
                {wch: 35}   // 型号
            ];
            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, "设备检查结果");
            // 生成Excel文件并下载 - 文件名精确到秒
            const now = new Date();
            const year = now.getFullYear();
            const month = String(now.getMonth() + 1).padStart(2, '0');
            const day = String(now.getDate()).padStart(2, '0');
            const hours = String(now.getHours()).padStart(2, '0');
            const minutes = String(now.getMinutes()).padStart(2, '0');
            const seconds = String(now.getSeconds()).padStart(2, '0');
            const fileName = `Verizon设备检查结果_${year}${month}${day}_${hours}${minutes}${seconds}.xlsx`;
            XLSX.writeFile(wb, fileName);
        } catch (e) {
            console.error('导出Excel失败:', e);
            alert('导出Excel失败: ' + e.message);
        }
    }

    // 拦截XHR请求 (保留原有功能，以防页面上的IMEI输入也能工作)
    const originalXHROpen = XMLHttpRequest.prototype.open;
    const originalXHRSend = XMLHttpRequest.prototype.send;

    XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
        // 记录原始URL，用于调试
        this._originalUrl = url;
        this._url = url;
        this._method = method; // 保存方法
        
        // 如果是validateDeviceId API调用，记录下来
        if (url && url.includes('validateDeviceId')) {
            console.log('检测到validateDeviceId API调用:', url);
            console.log('HTTP方法:', method);
        }
        
        return originalXHROpen.apply(this, arguments);
    };

    XMLHttpRequest.prototype.send = function(body) {
        const xhr = this;
        
        // 检查是否是validateDeviceId API调用
        if (xhr._url && xhr._url.includes('validateDeviceId')) {
            console.log('拦截到validateDeviceId API调用:', xhr._url);
            if (body) {
                console.log('请求体:', body);
            }
            
            // 获取IMEI
            let imei = '';
            if (xhr._method === 'POST' && body) {
                try {
                    const bodyObj = JSON.parse(body);
                    imei = bodyObj.deviceId || '';
                    console.log('检测到IMEI:', imei);
                } catch (e) {
                    console.error('解析请求体失败:', e);
                }
            } else if (xhr._method === 'GET') {
                // 从URL中提取IMEI
                const urlParams = new URLSearchParams(xhr._url.split('?')[1]);
                imei = urlParams.get('deviceId') || '';
                console.log('从URL检测到IMEI:', imei);
            }
            
            // 添加响应监听器
            const originalOnReadyStateChange = xhr.onreadystatechange;
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        try {
                            const response = JSON.parse(xhr.responseText);
                            console.log('validateDeviceId响应:', response);
                            
                            // 检查服务状态
                            if (response && response.serviceStatus) {
                                // 检查是否成功
                                if (response.serviceStatus.success === true) {
                                    // 成功响应，设备在白名单中
                                    const deviceInfo = response.deviceInfo || {};
                                    const deviceName = deviceInfo.brandName && deviceInfo.name ? 
                                        `${deviceInfo.brandName} ${deviceInfo.name}` : '未知设备';
                                    const statusMessage = `设备 ${imei} 状态: CLEAN (可用)\n设备型号: ${deviceName}`;
                                    
                                    // 不再直接更新状态，因为我们现在使用批量检查
                                    // updateStatus(statusMessage, true);
                                } else {
                                    // 失败响应，设备在黑名单中
                                    const errorMsg = response.serviceStatus.statusMessage || '未知错误';
                                    const statusMessage = `设备 ${imei} 状态: BLACKLISTED (黑名单)\n错误信息: ${errorMsg}`;
                                    
                                    // 不再直接更新状态，因为我们现在使用批量检查
                                    // updateStatus(statusMessage, false);
                                }
                            } else {
                                // 不再直接更新状态，因为我们现在使用批量检查
                                // updateStatus(`无法确定设备 ${imei} 的状态`, false);
                            }
                        } catch (e) {
                            console.error('解析响应失败:', e);
                            // updateStatus('解析响应失败', false);
                        }
                    } else {
                        // updateStatus(`API调用失败: ${xhr.status}`, false);
                    }
                }
                
                if (originalOnReadyStateChange) {
                    originalOnReadyStateChange.apply(xhr, arguments);
                }
            };
        }
        
        return originalXHRSend.apply(this, arguments);
    };

    // 初始化
    function init() {
        console.log('Verizon BYOD Device Checker 已初始化');
        
        // 检查是否已加载XLSX库
        if (!window.XLSX) {
            console.log('正在加载XLSX库...');
            const script = document.createElement('script');
            script.src = 'https://unpkg.com/xlsx/dist/xlsx.full.min.js';
            script.onload = function() {
                console.log('XLSX库加载成功');
                createStatusElement();
            };
            script.onerror = function() {
                console.error('XLSX库加载失败');
                alert('Excel导出功能加载失败，但设备检查功能仍可使用');
                createStatusElement();
            };
            document.head.appendChild(script);
        } else {
            createStatusElement();
        }
    }

    // 等待页面加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();